package pa5.components;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

import pa5.beans.MatchBean;

import com.google.appengine.api.ThreadManager;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.vaadin.annotations.AutoGenerated;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.ui.AbsoluteLayout;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.DateField;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;

import com.google.appengine.api.datastore.Query.*;



public class OutputComponent extends CustomComponent implements Button.ClickListener{

	@AutoGenerated
	private VerticalLayout mainLayout;
	@AutoGenerated
	private Table resultsTable;
	@AutoGenerated
	private TextField inputField;
	private TextField numValues;
	private boolean executed;
	@AutoGenerated
	private Button searchButton;
	private CheckBox switchEditable;
	private HorizontalLayout formControls;
	private GridLayout form;
	private HorizontalLayout tableControls;
	private HashMap<MatchBean, Entity> map = new HashMap<MatchBean, Entity>();
	private Thread[] threads = new Thread[5];

	//Form fields
	TextField player1;
	TextField player2;
	DateField date;
	TextField result;

	private MatchBean selectedMatch;

	private BeanItemContainer<MatchBean> matches = new BeanItemContainer<MatchBean>(MatchBean.class);	//the model for the table

	/**
	 * The constructor should first build the main layout, set the
	 * composition root and then do any custom initialization.
	 *
	 * The constructor will not be automatically regenerated by the
	 * visual editor.
	 */
	public OutputComponent() {
		buildMainLayout();
		setCompositionRoot(mainLayout);

		// TODO add user code here
	}

	@AutoGenerated
	private VerticalLayout buildMainLayout() {
		// common part: create layout
		mainLayout = new VerticalLayout();
		mainLayout.setSpacing(true);
		mainLayout.setMargin(true);
		mainLayout.setImmediate(false);
		mainLayout.setMargin(false);

		mainLayout.addComponent(buildTableControls());
		mainLayout.addComponent(buildTable());
		mainLayout.addComponent(buildForm());
		mainLayout.addComponent(buildFormControls());
		return mainLayout;
	}

	private Component buildFormControls() {
		formControls = new HorizontalLayout();
		Button save = new Button("Save", new Button.ClickListener() {

			public void buttonClick(ClickEvent event) {
				//Key playerKey = KeyFactory.createKey("Match", (String) player1.getValue());

				Entity matchEntry1 = new Entity("Match");  
				matchEntry1.setProperty("player1", (String) player1.getValue());
				matchEntry1.setProperty("player2", (String) player2.getValue());
				matchEntry1.setProperty("date", (Date)date.getValue());
				matchEntry1.setProperty("result", result.getValue());				

				DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();

				datastore.put(matchEntry1);	
			}
		});
		Button discard = new Button("Discard", new Button.ClickListener() {

			public void buttonClick(ClickEvent event) {
				player1.setValue("");
				player2.setValue("");
				date.setValue(new Date());
				result.setValue("");

			}
		});
		Button update = new Button("Update", new Button.ClickListener() {

			public void buttonClick(ClickEvent event) {
				if(selectedMatch != null){
					Entity selectedEntity = map.get(selectedMatch);
					selectedEntity.setProperty("player1", (String) player1.getValue());
					selectedEntity.setProperty("player2", (String) player2.getValue());
					selectedEntity.setProperty("date", (Date)date.getValue());
					selectedEntity.setProperty("result", result.getValue());

					DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
					datastore.put(selectedEntity);
				}
			}
		});

		formControls.addComponent(save);
		formControls.addComponent(discard);
		formControls.addComponent(update);
		return formControls;
	}

	private Component buildForm() {
		form = new GridLayout(2, 2);

		player1 = new TextField("Player 1:");
		player2 = new TextField("Player 2:");
		date = new DateField("Date:");
		result = new TextField("Result:");

		form.addComponent(player1);
		form.addComponent(player2);
		form.addComponent(date);
		form.addComponent(result);
		return form;
	}

	private Component buildTable() {
		resultsTable = new Table("Matches", matches);
		resultsTable.setSelectable(true);
		resultsTable.setImmediate(true);
		resultsTable.setWidth("760px");
		resultsTable.addListener(new Property.ValueChangeListener() {
			public void valueChange(ValueChangeEvent event) {
				selectedMatch = (MatchBean) resultsTable.getValue();
				editMatch();
			}
		});
		return resultsTable;
	}

	protected void editMatch() {
		player1.setValue(selectedMatch.getPlayer1());
		player2.setValue(selectedMatch.getPlayer2());
		date.setValue(selectedMatch.getDate());
		result.setValue(selectedMatch.getResult());
	}

	private Component buildTableControls() {
		tableControls = new HorizontalLayout();

		Button delete = new Button("Delete", new Button.ClickListener() {
			public void buttonClick(ClickEvent event) {
				if(selectedMatch != null){
					Entity selectedEntity = map.get(selectedMatch);
					DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
					datastore.delete(selectedEntity.getKey());
					matches.removeItem(selectedMatch);
				}
			}
		});
		inputField = new TextField();
		Button searchButton = new Button("Search", new Button.ClickListener() {

			public void buttonClick(ClickEvent event) {
				selectedMatch = null;
				matches.removeAllItems();
				String searchRequest = (String) inputField.getValue();
				DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
				Key playerKey = KeyFactory.createKey("Match", searchRequest);

				Query query = new Query("Match");

				query.setFilter(Query.CompositeFilterOperator.or(
						new FilterPredicate("player1", Query.FilterOperator.EQUAL, searchRequest),
						new FilterPredicate("player2", Query.FilterOperator.EQUAL, searchRequest)));
				/*
				Query query = new Query("Match", playerKey).addSort("date", Query.SortDirection.DESCENDING);
			    query.setAncestor(playerKey);*/
				List<Entity> results = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(10));


				for(Entity match: results){
					MatchBean matchBean = new MatchBean((String)match.getProperty("player1"), 
							(String)match.getProperty("player2"), 
							(Date)match.getProperty("date"), 
							(String)match.getProperty("result"));

					matches.addBean(matchBean);
					map.put(matchBean, match);
				}

			}
		});

		Label label1 = new Label("Add ");
		Label label2 = new Label(" Random Values");
		numValues = new TextField();


		Button addButton = new Button("Ok", new Button.ClickListener(){
			public void buttonClick(ClickEvent event) {
				final DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
				final int value = Integer.parseInt((String)numValues.getValue());
				for(int i = 0; i < value; i++){
					Entity matchEntry = new Entity("Match");  
					matchEntry.setProperty("player1", (String) UUID.randomUUID().toString());
					matchEntry.setProperty("player2", (String) UUID.randomUUID().toString());
					matchEntry.setProperty("date", new Date());
					matchEntry.setProperty("result", UUID.randomUUID().toString());	

					datastore.put(matchEntry);
				}	
			}
		});
		
		Button getAllButton = new Button("Get All Items", new Button.ClickListener(){
			public void buttonClick(ClickEvent event) {
				selectedMatch = null;
				matches.removeAllItems();
				DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
				Query query = new Query("Match");

				List<Entity> results = datastore.prepare(query).asList(FetchOptions.Builder.withDefaults());

				for(Entity match: results){
					MatchBean matchBean = new MatchBean((String)match.getProperty("player1"), 
							(String)match.getProperty("player2"), 
							(Date)match.getProperty("date"), 
							(String)match.getProperty("result"));

					matches.addBean(matchBean);
					map.put(matchBean, match);
				}
			}
		});

		tableControls.addComponent(inputField);
		tableControls.addComponent(searchButton);
		tableControls.addComponent(delete);
		//tableControls.addComponent(getAllButton);

		if(!executed){
			//tableControls.addComponent(label1);
			//tableControls.addComponent(numValues);
			//tableControls.addComponent(label2);
			//tableControls.addComponent(addButton);
		}


		return tableControls;
	}



	public void buttonClick(ClickEvent event) {
		if(event.getButton() == searchButton){
			matches.removeAllItems();
			map.clear();
			String searchRequest = (String) inputField.getValue();
			DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
			Key playerKey = KeyFactory.createKey("Match", searchRequest);

			Query query = new Query("Match", playerKey).addSort("date", Query.SortDirection.DESCENDING);
			query.setAncestor(playerKey);
			List<Entity> results = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(10));


			for(Entity match: results){
				matches.addBean(new MatchBean((String)match.getProperty("player1"), 
						(String)match.getProperty("player2"), 
						(Date)match.getProperty("date"), 
						(String)match.getProperty("result")));		    	
			}
		}		
	}

}